< previous page page_167 next page >

Page 167
What about Visual Basic?
Now you know what the API function expects to see. What are you actually passing to the function?
The lpIconParam parameter is declared ByVal As String. That means the function is always passed a NULL-terminated string. What happens when you pass a numeric constant to a parameter declared ByVal As String? Visual Basic converts it into a string before passing it to the function. This differs from the C language "cast" operator, where the data is unchanged and merely interpreted according to the new type. Visual Basic performs an actual conversion. In this case, the IDI_ASTERISK constant is converted into the string "32516" and passed, with a NULL terminator, to the function. This is illustrated in Figure S6-2.
0167-01.gif
Figure S6-2:
Passing the IDI_ASTERISK resource identifier when a parameter is 
declared ByVal As String
Naturally, this is not what the function expects to see, so it returns an error result.
Why doesn't Visual Basic report an error when you try to pass a number to a string parameter? Most computer scientists ask this question as wellit is one area where many of us fundamentally disagree with Microsoft's approach to Visual Basic. Microsoft has built many of these automatic type conversions into Visual Basic, supposedly to make the language easier for programmers. Unfortunately, this decision has eliminated the ability of the compiler to detect many types of errors. Visual Basic happily converts parameters without so much as a hint of what it is doing, leaving you to struggle with obscure bugs. We call this "evil type coercion," and you'll find many programmers (including myself) who consider this one of the greatest flaws in what is otherwise a superb programming language.
How should you handle a situation like this? You could just change the lpIconName parameter to be ByVal As Long, but if you take that approach, the function will not be able to use string parameters. You could declare the parameter to be As Any or ByVal As Any to allow you to call the function with either a string or numeric parameter.
You can also create two separate declarations, one for Long parameters and another for string parameters. This is the approach used in the final solution for this puzzle. The Visual Basic Alias keyword allows you to define a function name for a declaration in Visual Basic that differs from the function name within the DLL file. In this case, the LoadIconBynum declaration uses a Long parameter, and the LoadIconBystring declaration uses a string parameter. Both functions use the LoadIconA entry point in the DLL.

 
< previous page page_167 next page >